﻿//-----------------------------------------------------------------------
// <copyright file="FlipTileData.cs" company="Steve Syrell">
//     Copyright 2012 Steve Syrell
// </copyright>
//-----------------------------------------------------------------------

namespace SteveSyrell.Tools.Phone.LiveTiles
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.IO.IsolatedStorage;
    using System.Runtime.Serialization;
    using System.Windows;
    using Shell = Microsoft.Phone.Shell;

    /// <summary>
    /// Flip tile data.
    /// </summary>
    [DataContract]
    public class FlipTileData : TileData
    {
        /// <summary>
        /// Initializes a new instance of the FlipTileData class.
        /// </summary>
        public FlipTileData()
            : base()
        {
        }

        /// <summary>
        /// Gets or sets the UI to use for the small size tile.
        /// </summary>
        [IgnoreDataMember]
        public UIElement SmallTileUI { get; set; }

        /// <summary>
        /// Gets or sets the UI to use for the front of the medium size tile.
        /// </summary>
        [IgnoreDataMember]
        public UIElement MediumTileFrontUI { get; set; }

        /// <summary>
        /// Gets or sets the UI to use for the back of the medium size tile.
        /// </summary>
        [IgnoreDataMember]
        public UIElement MediumTileBackUI { get; set; }

        /// <summary>
        /// Gets or sets the UI to use for the front of the wide size tile.
        /// </summary>
        [IgnoreDataMember]
        public UIElement WideTileFrontUI { get; set; }

        /// <summary>
        /// Gets or sets the UI to use for the back of the wide size tile.
        /// </summary>
        [IgnoreDataMember]
        public UIElement WideTileBackUI { get; set; }

        /// <summary>
        /// Gets or sets the text to display on the back of the medium size tile.
        /// </summary>
        [DataMember]
        public string MediumBackContent { get; set; }

        /// <summary>
        /// Gets or sets the text to display on the back of the wide size tile.
        /// </summary>
        [DataMember]
        public string WideBackContent { get; set; }

        /// <summary>
        /// Gets or sets the title to display on the back of the tile.
        /// </summary>
        [DataMember]
        public string BackTitle { get; set; }

        /// <summary>
        /// Gets or sets the URI of the background image of the small size tile.
        /// </summary>
        [DataMember]
        public Uri SmallBackgroundImage { get; set; }

        /// <summary>
        /// Gets or sets the URI of the front background image of the medium size tile.
        /// </summary>
        [DataMember]
        public Uri MediumFrontBackgroundImage { get; set; }

        /// <summary>
        /// Gets or sets the URI of the back background image of the medium size tile.
        /// </summary>
        [DataMember]
        public Uri MediumBackBackgroundImage { get; set; }

        /// <summary>
        /// Gets or sets the URI of the front background image of the wide size tile.
        /// </summary>
        [DataMember]
        public Uri WideFrontBackgroundImage { get; set; }

        /// <summary>
        /// Gets or sets the URI of the back background image of the wide size tile.
        /// </summary>
        [DataMember]
        public Uri WideBackBackgroundImage { get; set; }

        /// <summary>
        /// Gets the system shell tile data that is used to actually create the tile in the system.
        /// </summary>
        /// <param name="verifyUiElements">A value indicating whether to verify UI elements.</param>
        /// <returns>The system shell tile data.</returns>
        internal override Shell.ShellTileData GetSystemShellTileData(bool verifyUiElements)
        {
            if (verifyUiElements)
            {
                // Make sure we have valid tile data.
                if (this.SmallTileUI == null)
                {
                    throw new InvalidOperationException("Small tile UI must be provided");
                }

                if (this.MediumTileFrontUI == null)
                {
                    throw new InvalidOperationException("Medium front tile UI must be provided");
                }

                if (this.WideTileBackUI != null && this.WideTileFrontUI == null)
                {
                    throw new InvalidOperationException("Wide tile front UI must be provided in order to use wide tile back ui");
                }
            }

            // Create all the background images.
            this.CreateAndSaveTileImages();

            // Now create the system tile data to return.
            Shell.FlipTileData tileDataToReturn = new Shell.FlipTileData
            {
                BackBackgroundImage = this.MediumBackBackgroundImage,
                BackContent = this.MediumBackContent,
                BackgroundImage = this.MediumFrontBackgroundImage,
                BackTitle = this.BackTitle,
                Count = this.Count,
                SmallBackgroundImage = this.SmallBackgroundImage,
                Title = this.Title,
                WideBackBackgroundImage = this.WideBackBackgroundImage,
                WideBackContent = this.WideBackContent,
                WideBackgroundImage = this.WideFrontBackgroundImage
            };

            return tileDataToReturn;
        }

        /// <summary>
        /// Cleans up all images created for this tile.
        /// </summary>
        internal override void CleanupResources()
        {
            if (this.SmallBackgroundImage != null)
            {
                this.DeleteTileImage(this.SmallBackgroundImage);
            }

            if (this.MediumFrontBackgroundImage != null)
            {
                this.DeleteTileImage(this.MediumFrontBackgroundImage);
            }

            if (this.MediumBackBackgroundImage != null)
            {
                this.DeleteTileImage(this.MediumBackBackgroundImage);
            }

            if (this.WideFrontBackgroundImage != null)
            {
                this.DeleteTileImage(this.WideFrontBackgroundImage);
            }

            if (this.WideBackBackgroundImage != null)
            {
                this.DeleteTileImage(this.WideBackBackgroundImage);
            }
        }

        /// <summary>
        /// Copies non-updated old tile data to this tile data instance.
        /// This is used when updating tile data if only new (updated) data is applied.
        /// </summary>
        /// <param name="oldTileData">The old tile data instance.</param>
        internal override void CopyNonUpdatedData(TileData oldTileData)
        {
            // First, cast the tile data to this specific tile data type.
            FlipTileData oldFlipTileData = oldTileData as FlipTileData;

            if (oldFlipTileData == null)
            {
                throw new InvalidOperationException("Updating to a different tile type is not supported.");
            }

            // For each of the tile images URIs, if this new instance's URI is null, it was not provided
            // and is not being updated. Therefore, use the existing (old) image.
            // For any images that we copy over to the new data, set it to null in the old data so that 
            // when we clean the old images up, we don't delete images that we're still using.
            if (this.SmallBackgroundImage == null)
            {
                this.SmallBackgroundImage = oldFlipTileData.SmallBackgroundImage;
                oldFlipTileData.SmallBackgroundImage = null;
            }

            if (this.MediumFrontBackgroundImage == null)
            {
                this.MediumFrontBackgroundImage = oldFlipTileData.MediumFrontBackgroundImage;
                oldFlipTileData.MediumFrontBackgroundImage = null;
            }

            if (this.MediumBackBackgroundImage == null)
            {
                this.MediumBackBackgroundImage = oldFlipTileData.MediumBackBackgroundImage;
                oldFlipTileData.MediumBackBackgroundImage = null;
            }

            if (this.WideFrontBackgroundImage == null)
            {
                this.WideFrontBackgroundImage = oldFlipTileData.WideFrontBackgroundImage;
                oldFlipTileData.WideFrontBackgroundImage = null;
            }

            if (this.WideBackBackgroundImage == null)
            {
                this.WideBackBackgroundImage = oldFlipTileData.WideBackBackgroundImage;
                oldFlipTileData.WideBackBackgroundImage = null;
            }
        }

        /// <summary>
        /// Gets a list of the file names of the images in use for this tile.
        /// </summary>
        /// <returns>A list of the file names of the images in use for this tile.</returns>
        internal override List<string> GetImageFileNames()
        {
            List<string> imageFileNames = new List<string>();

            if (this.SmallBackgroundImage != null)
            {
                imageFileNames.Add(Path.GetFileName(this.SmallBackgroundImage.ToString()));
            }

            if (this.MediumFrontBackgroundImage != null)
            {
                imageFileNames.Add(Path.GetFileName(this.MediumFrontBackgroundImage.ToString()));
            }

            if (this.MediumBackBackgroundImage != null)
            {
                imageFileNames.Add(Path.GetFileName(this.MediumBackBackgroundImage.ToString()));
            }

            if (this.WideFrontBackgroundImage != null)
            {
                imageFileNames.Add(Path.GetFileName(this.WideFrontBackgroundImage.ToString()));
            }

            if (this.WideBackBackgroundImage != null)
            {
                imageFileNames.Add(Path.GetFileName(this.WideBackBackgroundImage.ToString()));
            }

            return imageFileNames;
        }

        /// <summary>
        /// Creates and saves all images for this tile.
        /// </summary>
        protected override void CreateAndSaveTileImages()
        {
            // If UI was provided for the small tile, add it.
            if (this.SmallTileUI != null)
            {
                this.SmallBackgroundImage = this.CreateAndSaveTileImage(this.SmallTileUI, TileData.SmallTileSize);
                this.SmallTileUI = null;
                GC.Collect();
            }

            // If UI was provided for the front of the medium tile, add it.
            if (this.MediumTileFrontUI != null)
            {
                this.MediumFrontBackgroundImage = this.CreateAndSaveTileImage(this.MediumTileFrontUI, TileData.MediumTileSize);
                this.MediumTileFrontUI = null;
                GC.Collect();
            }
            
            // If UI was provided for the back of the medium tile, add it.
            if (this.MediumTileBackUI != null)
            {
                this.MediumBackBackgroundImage = this.CreateAndSaveTileImage(this.MediumTileBackUI, TileData.MediumTileSize);
                this.MediumTileBackUI = null;
                GC.Collect();
            }

            // If UI was provided for the front of the wide tile, add it.
            if (this.WideTileFrontUI != null)
            {
                this.WideFrontBackgroundImage = this.CreateAndSaveTileImage(this.WideTileFrontUI, TileData.WideTileSize);
                this.SupportsWideTile = true;
                this.WideTileFrontUI = null;
                GC.Collect();
            }

            // if UI was provided for the back of the wide tile, add it.
            if (this.WideTileBackUI != null)
            {
                this.WideBackBackgroundImage = this.CreateAndSaveTileImage(this.WideTileBackUI, TileData.WideTileSize);
                this.SupportsWideTile = true;
                this.WideTileBackUI = null;
                GC.Collect();
            }
        }
    }
}
